import { Vector2tuple, Vector3 } from 'three-legacy';
import DimBase from './DimBase';
import {
  AnnotationType,
  EllipseAttrs,
  EllipseState,
  EllipseType,
} from './types';
import {
  calculatePoint,
  distanceToLine,
  getDotProduct,
  RETAIN,
} from '@app-cad/common/utils';
import { MathTool, ParameterObjectType } from '@amcax/base';
import { ctx2 } from '@app-cad/module';

export class DimEllipseTool extends DimBase {
  private center: Vector3; // 本地坐标
  private major: number;
  private minor: number;
  private majorDir: Vector2tuple;
  private state: EllipseType = EllipseState.major;
  private relativePosition: Vector2tuple;
  private basePoints: Vector3[] = [];
  private transformPoints: Vector3[] = [];
  private vecs: { vec: Vector3; vertical: Vector3 } = {
    vec: null,
    vertical: null,
  };
  radius: number;
  radiusParam?: string;
  relPos: Vector2tuple[];

  constructor(attrs: EllipseAttrs) {
    super();
    this.setUserData({ type: AnnotationType.MajorRadiusAnno });
    this.init(attrs);
  }
  init(attrs: EllipseAttrs) {
    this.updateDisableIfCurvesFixed(attrs.curveIds);
    this.commonCall(attrs);
  }
  update(attrs: EllipseAttrs) {
    this.commonCall(attrs);
  }
  commonCall(attrs: EllipseAttrs) {
    this.setDimInfo(attrs);
    this.getCalPointsLine();
    this.createUpdateLines();
    this.createUpdateLabel(
      attrs,
      this.mouseXY,
      this.radius,
      ParameterObjectType.Length,
      2,
    );
  }
  createUpdateLines() {
    const [point3, point4] = this.transformPoints;
    const [point1, point2] = this.basePoints;
    // 创建箭头
    this.createArrow([point3, point4]);
    // 创建辅助线
    this.createUpdateLine('line1', this.extendLine([point3, point1]));
    this.createUpdateLine('line2', this.extendLine([point4, point2]));
    const l1 = this.mouseXY.distanceToSquared(point3);
    const l2 = this.mouseXY.distanceToSquared(point4);
    const l3 = point4.distanceToSquared(point3);
    let vertices = [point3, point4, point4];
    if (l3 < l1 || l3 < l2) {
      if (l1 > l2) {
        const [p2, p3] = this.extendLine([this.mouseXY, point4], 'minus');
        vertices = [point3, p2, p3];
      } else {
        const [p2, p3] = this.extendLine([this.mouseXY, point3], 'minus');
        vertices = [point4, p2, p3];
      }
      this.createUpdateLine('line3', vertices);
      this.removeLine(['line4']);
    } else {
      const [p1, p2] = this.extendLine([this.mouseXY, point3], 'minus');
      this.createUpdateLine('line3', [p1, p2, p2]);
      const [p3, p4] = this.extendLine([this.mouseXY, point4], 'minus');
      this.createUpdateLine('line4', [p3, p4, p4]);
    }
  }

  zoomUpdate() {
    const [point3, point4] = this.transformPoints;
    const [point1, point2] = this.basePoints;
    if (point3 && point1 && point2 && point4) {
      this.createUpdateLines();
      ctx2.viewer.requestRender();
    }
  }
  createArrow([startPoint, endPoint]) {
    this.updateArrow([startPoint, endPoint]);
  }
  // 根据短轴长轴获取点
  calcPointsBycenter() {
    const { vec } = this.vecs;
    const len = this.state === EllipseState.major ? this.major : this.minor;
    const p1 = calculatePoint(vec, len, this.center);
    const p2 = calculatePoint(vec, -len, this.center);
    this.basePoints = [p1, p2];
  }
  // 根据鼠标位置计算点
  getCalPointsLine() {
    const { vec, vertical } = this.vecs;
    const [p1, p2] = this.basePoints;
    const sign = getDotProduct(p2, this.mouseXY, vertical) >= 0 ? 1 : -1;
    const length = distanceToLine<Vector3>(this.mouseXY, {
      start: p1,
      vec: vec,
      normal: vertical,
    });
    const point4 = calculatePoint(vertical, length * sign, p2);
    const point3 = calculatePoint(vertical, length * sign, p1);
    const center = point3.clone().add(point4).multiplyScalar(0.5);
    const sign2 = getDotProduct(center, this.mouseXY, vec) >= 0 ? 1 : -1;
    this.relativePosition = [
      this.mouseXY.distanceTo(center) * sign2,
      length * sign,
    ];
    this.transformPoints = [point3, point4];
  }
  // 获取向量
  calcRaduisVec() {
    const vec = new Vector3(this.majorDir[0], this.majorDir[1], 0).normalize();
    const vec2 = new Vector3(-vec.y, vec.x, 0);
    if (this.state === EllipseState.major) {
      this.radius = this.major;
      this.vecs = { vec, vertical: vec2 };
    } else {
      this.radius = this.minor;
      this.vecs = { vec: vec2, vertical: vec };
    }
  }
  setDimInfo(attrs: EllipseAttrs) {
    if (attrs.center) {
      this.center = this.setV2ToV3(attrs.center);
    }
    if (attrs.major) {
      this.major = attrs.major;
    }
    if (attrs.minor) {
      this.minor = attrs.minor;
    }
    if (attrs.majorDir) {
      this.majorDir = attrs.majorDir;
    }
    if (attrs.dimConstraint) {
      this.userData.type = attrs.dimConstraint;
      this.state =
        attrs.dimConstraint === AnnotationType.MajorRadiusAnno
          ? EllipseState.major
          : EllipseState.minor;
    }
    if (attrs.curveIds) {
      this.userData.objects = attrs.curveIds;
    }
    if (attrs.center || attrs.major || attrs.minor || attrs.majorDir) {
      this.calcRaduisVec();
      this.calcPointsBycenter();
    }
    if (attrs.param != null) {
      this.radiusParam = attrs.param;
    }
    if (attrs.labelPos) {
      this.mouseXY = attrs.labelPos;
    } else {
      if (attrs.relPos?.length > 0) {
        this.relPos = attrs.relPos;
      } else {
        const xy = this.defaultDimPos();
        this.relPos = this.relPos || [[xy, 0]];
      }
      this.mouseXY = this.getCalPointsByPos(this.relPos);
    }
  }
  getPosLv(): Vector2tuple[] {
    const po1 = MathTool.fixNumber(this.relativePosition[0], RETAIN);
    const po2 = MathTool.fixNumber(this.relativePosition[1], RETAIN);
    this.userData.points = this.relPos = [[po1, po2]];
    return this.relPos;
  }
  // 根据相对位置计算点
  getCalPointsByPos(relPos: Vector2tuple[]) {
    const { vertical, vec } = this.vecs;
    const dimRelLength = relPos[0];
    const center = calculatePoint(vec, dimRelLength[0], this.center);
    return calculatePoint(vertical, dimRelLength[1], center);
  }
}
